package chapter

import scala.slick.driver.H2Driver
import scala.slick.driver.H2Driver.simple._
import scala.slick.direct._
import scala.slick.direct.AnnotationMapper._
import scala.reflect.runtime.universe
import scala.slick.jdbc.meta.MTable
import scala.slick.jdbc.{ GetResult, StaticQuery => Q }

@table("COFFEES") case class Coffee(
  @column("COF_NAME") name: String,
  @column("PRICE") price: Double)

//util
trait H2Support {
  val db = Database.forURL(
    url = "jdbc:h2:mem:test1",
    //    user = null,
    //    password = null,
    //    prop = null,
    driver = "org.h2.Driver")

  implicit val session = db.createSession

  def start() =
    if (MTable.getTables("coffees").list.isEmpty) {
      CoffeeDAO.createTable
    }

}
//dao
object CoffeeDAO extends H2Support {
  import Q.interpolation
  val backend = new SlickBackend(H2Driver, AnnotationMapper)
  def query[T](q: QueryableValue[T])(implicit session: Session): T = backend.result(q, session)
  def query[T](q: Queryable[T])(implicit session: Session): Vector[T] = backend.result(q, session)

  def createTable() {
    sqlu"create table COFFEES(COF_NAME varchar(255),PRICE DOUBLE)".execute
  }

  def save(coffees: Seq[Coffee]) =
    (for { c <- coffees } yield sqlu"insert into COFFEES values (${c.name},${c.price})".first).sum

  def dropTable() {
    sqlu"drop table COFFEES".execute
  }

  val coffees = Queryable[Coffee]
  val priceAbove3 = (coffees.filter(_.price > 3.0).map(_.name))
  val samePrice = for (c1 <- coffees; c2 <- coffees; if c1.price == c2.price) yield (c1.name, c2.name)

}

class SimpleExampleClass {
  import CoffeeDAO._

  db withSession { implicit session =>
    createTable
    val coffees_data = Vector(
      Coffee("Colombian", 2),
      Coffee("French_Roast", 2),
      Coffee("Espresso", 5),
      Coffee("Colombian_Decaf", 4),
      Coffee("French_Roast_Decaf", 5))

    save(coffees_data)
    // execute queries
    Seq(
      coffees,
      coffees.filter(_.price > 3.0).map(_.name), // inline query
      priceAbove3,
      samePrice).foreach(q => println(query(q)))

    println(priceAbove3.length)
  }

}

object SimpleExample extends SimpleExampleClass with App {

}